# coding=utf-8
'''
Created on 2014-3-25


'''
import torndb
import time
from queue import Queue

class PooledConnection(object):
    '''
    连接池静态实现:
        存活的连接的最大数量固定, 不会创建新的连接
    '''
    
    def __init__(self, max_connections, conn_name, db_args):
        self._pool = Queue(max_connections)  # create the queue
        
        self._conns = set()

        self.conn_name = conn_name
        self.db_args = db_args
        self.max_connections = max_connections
        
        for i in range(self.max_connections):
            self.fill_connection(self.create_connection())
    
    def fill_connection(self, conn):
        self._pool.put(conn)
        self._conns.add(conn)
    
    def return_connection(self, conn):
        self._pool.put(conn)
        
    def get_connection(self):
        return self._pool.get()
    
    def close(self):
        '''
        '''
        
        for conn in self._conns:
            try:
                conn.close()
            except:
                pass
    
    def create_connection(self):
        conn = torndb.Connection(**self.db_args)
        return conn
    
class MysqlConnPool(object):
    '''
    mysql连接池动态实现
    '''
    
    global_conns = dict()
    global_db_args = dict()  # 数据库参数
    global_pool_args = dict()  # 连接池参数
    
    locked = False
    
    @staticmethod
    def unlock():
        MysqlConnPool.locked = False
    
    @staticmethod
    def init_pool(db_name, db_args, **pool_args):
        '''
                        初始化连接池
        '''
        MysqlConnPool.global_pool_args[db_name] = dict()
        MysqlConnPool.global_pool_args[db_name]['max_idle'] = pool_args.get('max_idle', 10)
        MysqlConnPool.global_pool_args[db_name]['min_idle'] = pool_args.get('min_idle', 3)
        MysqlConnPool.global_pool_args[db_name]['init_count'] = pool_args.get('init_count', 5)
        
        MysqlConnPool.global_db_args[db_name] = db_args
        
        MysqlConnPool.global_conns[db_name] = set()
        for i in range(0, MysqlConnPool.global_pool_args[db_name]['init_count']):
            conn = MysqlConnPool.create_connection(db_name)
            MysqlConnPool.global_conns[db_name].add(conn)
            
#         print '...初始化...%s'% (len(MysqlConnPool.global_conns[db_name]))

    @staticmethod
    def create_connection(db_name):
        '''
        '''
        
        return torndb.Connection(**MysqlConnPool.global_db_args[db_name])

    def __init__(self, db_name):
        '''
        '''
        
        self.db_name = db_name
        self.conns = self.global_conns[db_name]
        self.db_args = self.global_db_args[db_name]
        self.pool_args = self.global_pool_args[db_name]
    
    def get_connection(self):
        '''
                        获取连接
        '''
        
        if self.locked:
            while True:
                if not self.locked:
                    break
                time.sleep(0.1)
            
        if len(self.conns) - 1 < self.pool_args['min_idle']:
            conn = MysqlConnPool.create_connection(self.db_name)
            self.conns.add(conn)
        conn = self.conns.pop()
        return conn
    
    @staticmethod
    def lock(clear=True):
        '''
        冻结连接池, 将连接池的max_idle设置为0, 以保证归还的连接被直接关闭
        '''
        
        MysqlConnPool.locked = True
        
        if clear:
            for db_name, db_conns in MysqlConnPool.global_conns.iteritems():
                for conn in db_conns: conn.close()
            MysqlConnPool.global_conns = dict()
        
    def close(self):
        
        while True:
            if self.conns:
                conn = self.conns.pop()
                if hasattr(conn, 'close'):
                    conn.close()
            else:
                break
            
    
    def release_connection(self, conn):
        '''
                        释放连接
        '''
        if self.locked or len(self.conns) + 1 > self.pool_args['max_idle']:
            conn.close()
        else:
            self.conns.add(conn)
